package com.iatinspur.learn;

import com.iatinspur.My;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 14集 讲解 【打破】双亲委派机制
 *  todo 为啥要打破
 *       一个AppClassLoader 要加载了两个名称相同的类 加载了一个可能另外一个就不能加载了，自定义两个个类加载器，当加载这个类时 我们就不要让AppClassLoader去加载
 *
 *  todo 打破双亲委派机制的三个方法
 *       1.自定义类加载器          一下代码做大概演示
 *       2.线程上下文类加载器
 *       3.Osgi框架的类加载器
 */
public class Learn_11_JVM {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InterruptedException {
        ClassLoader classLoader =new Learn_11_JVM_ClassLoader();

        // todo 打破双亲委派机制 然后再热部署
        while(true){
            Class<?> aClass = Learn_11_JVM.class.getClassLoader().loadClass("com.iatinspur.pojo.MyIml");
            My o =(My) aClass.newInstance();
            o.say();
            System.out.println(aClass.getClassLoader());

            /**
             *  todo 上述代码 o.say();  会输出【绿飞.say】
             *       类加载器是 AppClassLoader，所以随便怎么加载都会加载本地的 MyIml类
             *       现在 D:\myClass\文件  里面的say() 方法 是【黄飞.say】
             *       我要想使用这个class文件 就应该自定义一个类加载器
             *
             */
            Class<?> aClass1 = classLoader.loadClass("com.iatinspur.pojo.MyIml");
            My o1 =(My) aClass1.newInstance();
            o1.say();
            System.out.println(aClass1.getClassLoader());

            Thread.sleep(6000);
        }


    }

}



/**
 * loadClass     内部加载
 * findClass     根据路径找文件
 * defineClass   主要是加载虚拟机内存
 * resolveClass  主要是连接
 */
class Learn_11_JVM_ClassLoader extends ClassLoader{
   public static  Map<String,Class<?>> map=new HashMap<String,Class<?>>();


    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        if (name.startsWith("java.lang")) {
            return super.loadClass(name);
        }

        if (name.startsWith("java.io")) {
            return super.loadClass(name);
        }
        if (name.startsWith("com.iatinspur.My")) {
            return super.loadClass(name);
        }

        Class<?> loadedClass = findClass(name);
        if (loadedClass != null) {
            System.err.println("不空");
            return loadedClass;
        }
        InputStream in = null;
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        try {
            in = new FileInputStream(new File("D:\\myClass\\MyIml.class"));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        byte[] buf = new byte[1024];
        int temp;
        try {
            while((temp=in.read(buf))!=-1){
                bo.write(buf, 0, temp);
            }
        }catch (IOException e){

        }
        System.out.println(bo.toByteArray().length);
        Class<?> aClass = defineClass(name, bo.toByteArray(), 0, bo.toByteArray().length);
        map.put(name, aClass);
        return aClass;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        return map.get(name);
    }
}


